package cn.edu.wfit.modules.directionmanagement.util;

import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * 代码安全检查工具类
 */
public class CodeSecurityUtil {
    
    // 危险关键字列表（Java）
    private static final Set<String> JAVA_DANGEROUS_KEYWORDS = new HashSet<>(Arrays.asList(
        "runtime.getruntime()", "system.exit", "file", "fileinputstream", "fileoutputstream",
        "filereader", "filewriter", "randomaccessfile", "filechannel", "files",
        "processbuilder", "runtime.exec", "classloader", "urlclassloader",
        "thread", "runnable", "executorservice", "forkjoinpool",
        "socket", "serversocket", "datagramsocket", "networkinterface",
        "securitymanager", "accesscontroller", "privilegedaction",
        "reflection", "method.invoke", "field.set", "constructor.newinstance",
        "system.getproperty", "system.setproperty", "system.getenv"
    ));
    
    // 危险关键字列表（Python）
    private static final Set<String> PYTHON_DANGEROUS_KEYWORDS = new HashSet<>(Arrays.asList(
        "os.system", "os.popen", "subprocess", "exec", "eval", "compile",
        "open", "file", "import os", "import sys", "import subprocess",
        "socket", "urllib", "urllib2", "urllib.request", "requests",
        "threading", "multiprocessing", "pickle", "shelve", "marshal",
        "__import__", "execfile", "input", "raw_input", "globals", "locals"
    ));
    
    // 危险关键字列表（C++）
    private static final Set<String> CPP_DANGEROUS_KEYWORDS = new HashSet<>(Arrays.asList(
        "system", "popen", "fork", "exec", "socket", "unlink", "remove",
        "rename", "chmod", "chown", "kill", "signal", "ptrace",
        "mmap", "mprotect", "dlopen", "createprocess", "winexec",
        "shellexecute", "fopen", "freopen", "ifstream", "ofstream",
        "unistd.h", "sys/socket.h", "netinet/in.h", "windows.h"
    ));
    
    // 危险文件路径模式
    private static final Pattern[] DANGEROUS_PATH_PATTERNS = {
        Pattern.compile("(/etc/)|(/usr/bin/)|(/bin/)|(/sbin/)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("([A-Z]:\\\\windows\\\\)|([A-Z]:\\\\program files)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("(/root/)|(/home/)", Pattern.CASE_INSENSITIVE),
        Pattern.compile("(c:\\\\windows\\\\)|(c:\\\\program files)", Pattern.CASE_INSENSITIVE)
    };
    
    // 允许的命令白名单
    private static final Set<String> ALLOWED_COMMANDS = new HashSet<>(Arrays.asList(
        "javac", "java", "python", "g++", "gcc"
    ));
    
    /**
     * 检查Java代码是否包含危险关键字
     * @param sourceCode 源代码
     * @return 是否安全
     */
    public static boolean isJavaCodeSafe(String sourceCode) {
        if (sourceCode == null || sourceCode.isEmpty()) {
            return true;
        }
        
        String code = sourceCode.toLowerCase();
        for (String keyword : JAVA_DANGEROUS_KEYWORDS) {
            if (code.contains(keyword)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 检查Python代码是否包含危险关键字
     * @param sourceCode 源代码
     * @return 是否安全
     */
    public static boolean isPythonCodeSafe(String sourceCode) {
        if (sourceCode == null || sourceCode.isEmpty()) {
            return true;
        }
        
        String code = sourceCode.toLowerCase();
        for (String keyword : PYTHON_DANGEROUS_KEYWORDS) {
            if (code.contains(keyword)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 检查C++代码是否包含危险关键字
     * @param sourceCode 源代码
     * @return 是否安全
     */
    public static boolean isCppCodeSafe(String sourceCode) {
        if (sourceCode == null || sourceCode.isEmpty()) {
            return true;
        }
        
        String code = sourceCode.toLowerCase();
        for (String keyword : CPP_DANGEROUS_KEYWORDS) {
            if (code.contains(keyword)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 检查命令是否在白名单中
     * @param command 命令
     * @return 是否允许
     */
    public static boolean isCommandAllowed(String[] command) {
        if (command == null || command.length == 0) {
            return false;
        }
        
        String cmd = command[0].toLowerCase();
        return ALLOWED_COMMANDS.contains(cmd);
    }
    
    /**
     * 检查文件路径是否安全
     * @param filePath 文件路径
     * @return 是否安全
     */
    public static boolean isFilePathSafe(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return true;
        }
        
        String path = filePath.toLowerCase();
        // 检查是否包含危险路径模式
        for (Pattern pattern : DANGEROUS_PATH_PATTERNS) {
            if (pattern.matcher(path).find()) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查工作目录是否在系统临时目录下
     * @param workingDir 工作目录
     * @return 是否安全
     */
    public static boolean isWorkingDirectoryInTemp(String workingDir) {
        if (workingDir == null || workingDir.isEmpty()) {
            return false;
        }
        
        try {
            String tempDir = System.getProperty("java.io.tmpdir");
            String workingDirPath = new File(workingDir).getCanonicalPath();
            String tempDirPath = new File(tempDir).getCanonicalPath();
            
            return workingDirPath.startsWith(tempDirPath);
        } catch (Exception e) {
            return false;
        }
    }
}